home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / TitledBorder.java < prev    next >
Text File  |  1998-06-30  |  17KB  |  492 lines

  1. /*
  2.  * @(#)TitledBorder.java    1.16 98/02/02
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20. package com.sun.java.swing.border;
  21.  
  22. import java.awt.Graphics;
  23. import java.awt.Insets;
  24. import java.awt.Rectangle;
  25. import java.awt.Color;
  26. import java.awt.Font;
  27. import java.awt.FontMetrics;
  28. import java.awt.Point;
  29. import java.awt.Toolkit;
  30. import java.awt.Component;
  31. import java.awt.Dimension;
  32.  
  33. import com.sun.java.swing.UIManager;
  34.  
  35. /**
  36.  * A class which implements an arbitrary border
  37.  * with the addition of a String title in a
  38.  * specified position and justification.
  39.  * <p>
  40.  * Warning: serialized objects of this class will not be compatible with
  41.  * future swing releases.  The current serialization support is appropriate
  42.  * for short term storage or RMI between Swing1.0 applications.  It will
  43.  * not be possible to load serialized Swing1.0 objects with future releases
  44.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  45.  * baseline for the serialized form of Swing objects.
  46.  *
  47.  * @version 1.16 02/02/98 
  48.  * @author David Kloba
  49.  */
  50. public class TitledBorder extends AbstractBorder
  51. {
  52.     protected String title;
  53.     protected Border border;
  54.     protected int    titlePosition;
  55.     protected int    titleJustification;
  56.     protected Font   titleFont;
  57.     protected Color  titleColor;
  58.  
  59.     static public final int     DEFAULT_POSITION        = 0;
  60.     static public final int     ABOVE_TOP       = 1;
  61.     static public final int     TOP             = 2;
  62.     static public final int     BELOW_TOP       = 3;
  63.     static public final int     ABOVE_BOTTOM    = 4;
  64.     static public final int     BOTTOM          = 5;
  65.     static public final int     BELOW_BOTTOM    = 6;
  66.  
  67.     static public final int     DEFAULT_JUSTIFICATION   = 0;
  68.     static public final int     LEFT    = 1;
  69.     static public final int     CENTER  = 2;
  70.     static public final int     RIGHT   = 3;
  71.  
  72.     // Space between the border and the component's edge
  73.     static protected final int EDGE_SPACING = 2;
  74.  
  75.     // Space between the border and text
  76.     static protected final int TEXT_SPACING = 2;
  77.  
  78.     // Horizontal inset of text that is left or right justified
  79.     static protected final int TEXT_INSET_H = 5;
  80.  
  81.     /**
  82.      * Creates a TitledBorder instance which uses an etched border.
  83.      * 
  84.      * @param title  the title the border should display
  85.      */
  86.     public TitledBorder(String title)     {
  87.         this(null, title, LEFT, TOP, null, null);
  88.     }
  89.  
  90.     /**
  91.      * Creates a TitledBorder instance with the specified border
  92.      * and an empty title.
  93.      * 
  94.      * @param border  the border
  95.      */
  96.     public TitledBorder(Border border)       {
  97.         this(border, "", LEFT, TOP, null, null);
  98.     }
  99.  
  100.     /**
  101.      * Creates a TitledBorder instance with the specified border
  102.      * and title.
  103.      * 
  104.      * @param border  the border
  105.      * @param title  the title the border should display
  106.      */
  107.     public TitledBorder(Border border, String title) {
  108.         this(border, title, LEFT, TOP, null, null);
  109.     }
  110.  
  111.     /**
  112.      * Creates a TitledBorder instance with the specified border,
  113.      * title, title-justification, and title-position.
  114.      * 
  115.      * @param border  the border
  116.      * @param title  the title the border should display
  117.      * @param titleJustification the justification for the title
  118.      * @param titlePosition the position for the title
  119.      */
  120.     public TitledBorder(Border border, 
  121.                         String title,
  122.                         int titleJustification,
  123.                         int titlePosition)      {
  124.         this(border, title, titleJustification,
  125.                         titlePosition, null, null);
  126.     }
  127.  
  128.     /**
  129.      * Creates a TitledBorder instance with the specified border,
  130.      * title, title-justification, title-position, and title-font.
  131.      * 
  132.      * @param border  the border
  133.      * @param title  the title the border should display
  134.      * @param titleJustification the justification for the title
  135.      * @param titlePosition the position for the title
  136.      * @param titleFont the font for rendering the title
  137.      */
  138.     public TitledBorder(Border border,             
  139.                         String title,
  140.                         int titleJustification,
  141.                         int titlePosition,
  142.                         Font titleFont) {
  143.         this(border, title, titleJustification,
  144.                         titlePosition, titleFont, null);
  145.     }
  146.  
  147.     /**
  148.      * Creates a TitledBorder instance with the specified border,
  149.      * title, title-justification, title-position, title-font, and
  150.      * title-color.
  151.      * 
  152.      * @param border  the border
  153.      * @param title  the title the border should display
  154.      * @param titleJustification the justification for the title
  155.      * @param titlePosition the position for the title
  156.      * @param titleFont the font of the title
  157.      * @param titleColor the color of the title
  158.      */
  159.     public TitledBorder(Border border,                     
  160.                         String title,
  161.                         int titleJustification,
  162.                         int titlePosition,
  163.                         Font titleFont,
  164.                         Color titleColor)       {
  165.         this.title = title;
  166.         this.border = border;
  167.         this.titleFont = titleFont;
  168.         this.titleColor = titleColor;
  169.  
  170.         setTitleJustification(titleJustification);
  171.         setTitlePosition(titlePosition);
  172.     }
  173.  
  174.     /**
  175.      * Paints the border for the specified component with the 
  176.      * specified position and size.
  177.      * @param c the component for which this border is being painted
  178.      * @param g the paint graphics
  179.      * @param x the x position of the painted border
  180.      * @param y the y position of the painted border
  181.      * @param width the width of the painted border
  182.      * @param height the height of the painted border
  183.      */
  184.     public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
  185.  
  186.         if (getTitle() == null || getTitle().equals("")) {
  187.             getBorder().paintBorder(c, g, x, y, width, height);
  188.             return;
  189.         }
  190.  
  191.         Rectangle grooveRect = new Rectangle(EDGE_SPACING, EDGE_SPACING,
  192.                                              width - (EDGE_SPACING * 2),
  193.                                              height - (EDGE_SPACING * 2));
  194.         Font font = g.getFont();
  195.         Color color = g.getColor();
  196.  
  197.         g.setFont(getFont(c));
  198.  
  199.         FontMetrics fm = g.getFontMetrics();
  200.         int         fontHeight = fm.getHeight();
  201.         int         descent = fm.getDescent();
  202.         int         ascent = fm.getAscent();
  203.         Point       textLoc = new Point();
  204.         int         diff;
  205.         int         stringWidth = fm.stringWidth(getTitle());
  206.         Insets      insets;
  207.  
  208.         if(getBorder() != null)
  209.             insets = getBorder().getBorderInsets(c);
  210.         else
  211.             insets = new Insets(0, 0, 0, 0);
  212.  
  213.         switch (getTitlePosition()) {
  214.             case ABOVE_TOP:
  215.                 diff = ascent + descent + (Math.max(EDGE_SPACING,
  216.                                 TEXT_SPACING*2) - EDGE_SPACING);
  217.                 grooveRect.y += diff;
  218.                 grooveRect.height -= diff;
  219.                 textLoc.y = grooveRect.y - (descent + TEXT_SPACING);
  220.                 break;
  221.             case TOP:
  222.             case DEFAULT_POSITION:
  223.                 diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - EDGE_SPACING);
  224.                 grooveRect.y += diff;
  225.                 grooveRect.height -= diff;
  226.                 textLoc.y = (grooveRect.y - descent) +
  227.                 (insets.top + ascent + descent)/2;
  228.                 break;
  229.             case BELOW_TOP:
  230.                 textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING;
  231.                 break;
  232.             case ABOVE_BOTTOM:
  233.                 textLoc.y = (grooveRect.y + grooveRect.height) -
  234.                 (insets.bottom + descent + TEXT_SPACING);
  235.                 break;
  236.             case BOTTOM:
  237.                 grooveRect.height -= fontHeight/2;
  238.                 textLoc.y = ((grooveRect.y + grooveRect.height) - descent) +
  239.                         ((ascent + descent) - insets.bottom)/2;
  240.                 break;
  241.             case BELOW_BOTTOM:
  242.                 grooveRect.height -= fontHeight;
  243.                 textLoc.y = grooveRect.y + grooveRect.height + ascent +
  244.                         TEXT_SPACING;
  245.                 break;
  246.         }
  247.  
  248.         getBorder().paintBorder(c, g, grooveRect.x, grooveRect.y,
  249.                                   grooveRect.width, grooveRect.height);
  250.  
  251.         switch (getTitleJustification()) {
  252.             case LEFT:
  253.             case DEFAULT_JUSTIFICATION:
  254.                 textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left;
  255.                 break;
  256.             case RIGHT:
  257.                 textLoc.x = (grooveRect.x + grooveRect.width) -
  258.                         (stringWidth + TEXT_INSET_H + insets.right);
  259.                 break;
  260.             case CENTER:
  261.                 textLoc.x = grooveRect.x +
  262.                         ((grooveRect.width - stringWidth) / 2);
  263.                 break;
  264.         }
  265.     g.setColor(c.getBackground());
  266.         g.fillRect(textLoc.x - TEXT_SPACING, textLoc.y - (fontHeight-descent),
  267.                    stringWidth + (2 * TEXT_SPACING), fontHeight - descent);
  268.         g.setColor(getTitleColor());
  269.         g.drawString(getTitle(), textLoc.x, textLoc.y);
  270.  
  271.         g.setFont(font);
  272.         g.setColor(color);
  273.     }
  274.  
  275.     /**
  276.      * Returns the insets of the border.
  277.      * @param c the component for which this border insets value applies
  278.      */
  279.     public Insets getBorderInsets(Component c)       {
  280.         Insets retval;
  281.         FontMetrics fm;
  282.         int         descent = 0;
  283.         int         ascent = 16;
  284.  
  285.         if(getBorder() != null) {
  286.                 retval = getBorder().getBorderInsets(c);
  287.         } else
  288.                 retval = new Insets(0, 0, 0, 0);
  289.  
  290.         retval.left += EDGE_SPACING + TEXT_SPACING;
  291.         retval.right += EDGE_SPACING + TEXT_SPACING;
  292.         retval.top += EDGE_SPACING + TEXT_SPACING;
  293.         retval.bottom += EDGE_SPACING + TEXT_SPACING;
  294.  
  295.         if(c == null || getTitle() == null || getTitle().equals(""))    {
  296.             return retval;
  297.         }
  298.  
  299.         Font font = getFont(c);
  300.  
  301.         fm = c.getFontMetrics(font);
  302.  
  303.     if(fm != null) {
  304.          descent = fm.getDescent();
  305.        ascent = fm.getAscent();
  306.     }
  307.  
  308.         switch (getTitlePosition()) {
  309.           case ABOVE_TOP:
  310.               retval.top += ascent + descent
  311.                             + (Math.max(EDGE_SPACING, TEXT_SPACING*2)
  312.                             - EDGE_SPACING);
  313.               break;
  314.           case TOP:
  315.           case DEFAULT_POSITION:
  316.               retval.top += ascent + descent;
  317.               break;
  318.           case BELOW_TOP:
  319.               retval.top += ascent + descent + TEXT_SPACING;
  320.               break;
  321.           case ABOVE_BOTTOM:
  322.               retval.bottom += ascent + descent + TEXT_SPACING;
  323.               break;
  324.           case BOTTOM:
  325.               retval.bottom += ascent + descent;
  326.               break;
  327.           case BELOW_BOTTOM:
  328.               retval.bottom += ascent + TEXT_SPACING;
  329.               break;
  330.         }
  331.  
  332.         return retval;
  333.     }
  334.  
  335.     /**
  336.      * Returns whether or not the border is opaque.
  337.      */
  338.     public boolean isBorderOpaque() { return false; }
  339.  
  340.     /**
  341.      * Returns the title of the titled border.
  342.      */
  343.     public String getTitle()        {       return title;   }
  344.  
  345.     /**
  346.      * Returns the border of the titled border.
  347.      */
  348.     public Border getBorder()       {       
  349.         Border b = border;
  350.     if (b == null)
  351.         b = UIManager.getBorder("TitledBorder.border");
  352.         return b; 
  353.     }
  354.  
  355.     /**
  356.      * Returns the title-position of the titled border.
  357.      */
  358.     public int getTitlePosition()   {       return titlePosition;   }
  359.  
  360.     /**
  361.      * Returns the title-justification of the titled border.
  362.      */
  363.     public int getTitleJustification()      {       return titleJustification;      }
  364.  
  365.     /**
  366.      * Returns the title-font of the titled border.
  367.      */
  368.     public Font getTitleFont()      {       
  369.         Font f = titleFont;
  370.     if (f == null)
  371.         f = UIManager.getFont("TitledBorder.font");
  372.         return f;       
  373.     }
  374.  
  375.     /**
  376.      * Returns the title-color of the titled border.
  377.      */
  378.     public Color getTitleColor()    {       
  379.         Color c = titleColor;
  380.     if (c == null)
  381.         c = UIManager.getColor("TitledBorder.titleColor");
  382.         return c;  
  383.     }
  384.  
  385.  
  386.     // REMIND(aim): remove all or some of these set methods?
  387.  
  388.     /**
  389.      * Sets the title of the titled border.
  390.      * param title the title for the border
  391.      */
  392.     public void setTitle(String title)      {       this.title = title;     }
  393.  
  394.     /**
  395.      * Sets the border of the titled border.
  396.      * @param border the border
  397.      */
  398.     public void setBorder(Border border)    {       this.border = border;   }
  399.  
  400.     /**
  401.      * Sets the title-position of the titled border.
  402.      * @param titlePosition the position for the border
  403.      */
  404.     public void setTitlePosition(int titlePosition) {
  405.         switch (titlePosition) {
  406.           case ABOVE_TOP:
  407.           case TOP:
  408.           case BELOW_TOP:
  409.           case ABOVE_BOTTOM:
  410.           case BOTTOM:
  411.           case BELOW_BOTTOM:
  412.           case DEFAULT_POSITION:
  413.                 this.titlePosition = titlePosition;
  414.                 break;
  415.           default:
  416.             throw new IllegalArgumentException(titlePosition +
  417.                                         " is not a valid title position.");
  418.         }
  419.     }
  420.  
  421.     /**
  422.      * Sets the title-justification of the titled border.
  423.      * @param titleJustification the justification for the border
  424.      */
  425.     public void setTitleJustification(int titleJustification)       {
  426.         switch (titleJustification) {
  427.           case LEFT:
  428.           case CENTER:
  429.           case RIGHT:
  430.           case DEFAULT_JUSTIFICATION:
  431.             this.titleJustification = titleJustification;
  432.             break;
  433.           default:
  434.             throw new IllegalArgumentException(titleJustification +
  435.                                         " is not a valid title justification.");
  436.         }
  437.     }
  438.  
  439.     /**
  440.      * Sets the title-font of the titled border.
  441.      * @param titleFont the font for the border title
  442.      */
  443.     public void setTitleFont(Font titleFont) {       
  444.         this.titleFont = titleFont;     
  445.     }
  446.  
  447.     /**
  448.      * Sets the title-color of the titled border.
  449.      * @param titleColor the color for the border title
  450.      */
  451.     public void setTitleColor(Color titleColor) {       
  452.       this.titleColor = titleColor;   
  453.     }
  454.  
  455.     /**
  456.      * Returns the minimum dimensions this border requires
  457.      * in order to fully display the border and title.
  458.      * @param c the component where this border will be drawn
  459.      */
  460.     public Dimension getMinimumSize(Component c) {
  461.         Insets insets = getBorderInsets(c);
  462.         Dimension minSize = new Dimension(insets.right+insets.left, 
  463.                                           insets.top+insets.bottom);
  464.         Font font = getFont(c);
  465.         FontMetrics fm = c.getFontMetrics(font);
  466.         switch (titlePosition) {
  467.           case ABOVE_TOP:
  468.           case BELOW_BOTTOM:
  469.               minSize.width = Math.max(fm.stringWidth(getTitle()), minSize.width);
  470.               break;
  471.           case BELOW_TOP:
  472.           case ABOVE_BOTTOM:
  473.           case TOP:
  474.           case BOTTOM:
  475.           case DEFAULT_POSITION:       
  476.           default:
  477.               minSize.width += fm.stringWidth(getTitle());
  478.         }
  479.         return minSize;       
  480.     }
  481.  
  482.     protected Font getFont(Component c) {
  483.         Font font;
  484.         if ((font = getTitleFont()) != null) {
  485.             return font;
  486.         } else if (c != null && (font = c.getFont()) != null) {
  487.             return font;
  488.         } 
  489.         return new Font("Dialog", Font.PLAIN, 12);
  490.     }       
  491. }
  492.